package com.ydj.framework.log;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.filter.LevelFilter;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
import ch.qos.logback.core.spi.FilterReply;
import ch.qos.logback.core.util.FileSize;
import ch.qos.logback.core.util.OptionHelper;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class YdjLoggerBuilder {
    private static String pattern="|%d|%5p|%15t|%-40logger{39}|行数:%5L|%msg%n";

    private static final Map<String, Logger> container = new HashMap<>();

    public static Logger getLogger(Class className,String businessName) {
        Logger logger = container.get(businessName);
        if(logger != null) {
            return logger;
        }
        synchronized (YdjLoggerBuilder.class) {
            logger = container.get(businessName);
            if(logger != null) {
                return logger;
            }
            logger = build(className,businessName);
            container.put(businessName,logger);
        }
        return logger;
    }

    private static Logger build(Class className,String businessName) {
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger logger = context.getLogger(className.getName());
        RollingFileAppender<ILoggingEvent> errorAppender = getAppender(businessName, Level.ERROR, context);
        RollingFileAppender<ILoggingEvent> infoAppender = getAppender(businessName, Level.INFO, context);
        RollingFileAppender<ILoggingEvent> warnAppender = getAppender(businessName, Level.WARN, context);
        RollingFileAppender<ILoggingEvent> debugAppender = getAppender(businessName, Level.DEBUG, context);
        ConsoleAppender<ILoggingEvent> consoleAppender = getConsoleAppender(businessName, Level.DEBUG, context);

        //设置不向上级打印信息
        logger.setAdditive(false);
        logger.addAppender(errorAppender);
        logger.addAppender(infoAppender);
        logger.addAppender(warnAppender);
        logger.addAppender(debugAppender);
        logger.addAppender(consoleAppender);
        return logger;
    }

    private static RollingFileAppender<ILoggingEvent> getAppender(String name, Level level,LoggerContext context ){
//        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        //这里是可以用来设置appender的，在xml配置文件里面，是这种形式：
        // <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<>();
        //设置上下文，每个logger都关联到logger上下文，默认上下文名称为default。
        // 但可以使用<contextName>设置成其他名字，用于区分不同应用程序的记录。一旦设置，不能修改。
        appender.setContext(context);
        //appender的name属性
        appender.setName(name);
        String fp = OptionHelper.substVars("store-logs/"+level.levelStr +"-%d{yyyy-MM-dd}.%i.log",context);
        //设置文件名
//        appender.setFile(fp);
        appender.setAppend(true);
        appender.setPrudent(false);

        //设置文件创建时间及大小的类
        SizeAndTimeBasedRollingPolicy policy = new SizeAndTimeBasedRollingPolicy();
        //设置上下文，每个logger都关联到logger上下文，默认上下文名称为default。
        // 但可以使用<contextName>设置成其他名字，用于区分不同应用程序的记录。一旦设置，不能修改。
        policy.setContext(context);
        //文件名格式
        //最大日志文件大小
        policy.setMaxFileSize(FileSize.valueOf("100MB"));
        //设置文件名模式
        policy.setFileNamePattern(fp);
        //设置最大历史记录为15条
        policy.setMaxHistory(60);
        //总大小限制
        policy.setTotalSizeCap(FileSize.valueOf("20GB"));
        //设置父节点是appender
        policy.setParent(appender);

        policy.start();

        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        //设置上下文，每个logger都关联到logger上下文，默认上下文名称为default。
        // 但可以使用<contextName>设置成其他名字，用于区分不同应用程序的记录。一旦设置，不能修改。
        encoder.setContext(context);
        //设置格式
        encoder.setPattern("【"+name+"】"+pattern);
        encoder.start();

        //这里设置级别过滤器
        LevelFilter levelFilter = new LevelFilter();
        levelFilter.setLevel(level);
        levelFilter.setOnMatch(FilterReply.ACCEPT);
        levelFilter.setOnMismatch(FilterReply.DENY);
        levelFilter.start();

        //加入下面两个节点
        appender.setRollingPolicy(policy);
        appender.setEncoder(encoder);
        appender.addFilter(levelFilter);
        appender.start();
        return appender;
    }

    private static ConsoleAppender<ILoggingEvent> getConsoleAppender(String name, Level level,LoggerContext context ){
//        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
        consoleAppender.setContext(context);
        consoleAppender.setName(name);
        ThresholdFilter filter=new ThresholdFilter();
        filter.setLevel(level.levelStr);
        filter.start();

        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        //设置上下文，每个logger都关联到logger上下文，默认上下文名称为default。
        // 但可以使用<contextName>设置成其他名字，用于区分不同应用程序的记录。一旦设置，不能修改。
        encoder.setContext(context);
        //设置格式
        encoder.setPattern("【"+name+"】"+pattern);
        encoder.start();
        consoleAppender.addFilter(filter);
        consoleAppender.setEncoder(encoder);
        consoleAppender.start();
        return consoleAppender;
    }
}